/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.jk.config;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Vector;

import org.w3c.dom.Node;

/* Naming conventions:

 JK_CONF_DIR == serverRoot/work  ( XXX /jkConfig ? )

 - Each vhost has a sub-dir named after the canonycal name

 - For each webapp in a vhost, there is a separate WEBAPP_NAME.jkmap

 - In httpd.conf ( or equivalent servers ), in each virtual host you
 should "Include JK_CONF_DIR/VHOST/jk_apache.conf". The config
 file will contain the Alias declarations and other rules required
 for apache operation. Same for other servers. 

 - WebXml2Jk will be invoked by a config tool or automatically for each
 webapp - it'll generate the WEBAPP.jkmap files and config fragments.

 WebXml2Jk will _not_ generate anything else but mappings.
 It should _not_ try to guess locations or anything else - that's
 another components' job.

 */

/**
 * 
 * @author Costin Manolache
 */
public class GeneratorApache2 implements WebXml2Jk.MappingGenerator {
	WebXml2Jk wxml;
	String vhost;
	String cpath;
	String worker;
	PrintWriter out;

	public void setWebXmlReader(WebXml2Jk wxml) {
		this.wxml = wxml;
		vhost = wxml.vhost;
		cpath = wxml.cpath;
		worker = wxml.worker;
	}

	public void generateStart() throws IOException {
		File base = wxml.getJkDir();
		File outF = new File(base, "jk2.conf");
		out = new PrintWriter(new FileWriter(outF));

		out
				.println("# Must be included in a virtual host context for "
						+ vhost);

		out.println("Alias " + cpath + " \"" + wxml.docBase + "\"");
		out.println("<Directory \"" + wxml.docBase + "\" >");
		out.println("  Options Indexes FollowSymLinks");
		generateMimeMapping(out);
		generateWelcomeFiles(out);

		// If we use this instead of extension mapping for jsp we can avoid most
		// jsp security problems.
		out.println("  AddHandler jakarta-servlet2 .jsp");
		out.println("</Directory>");
		out.println();

		out.println("<Location \"" + cpath + "/WEB-INF\" >");
		out.println("  AllowOverride None");
		out.println("  Deny from all");
		out.println("</Location>");
		out.println();
		out.println("<Location \"" + cpath + "/META-INF\" >");
		out.println("  AllowOverride None");
		out.println("  Deny from all");
		out.println("</Location>");
		out.println();
	}

	private void generateWelcomeFiles(PrintWriter out) {
		Vector wf = wxml.getWellcomeFiles();
		out.print("  DirectoryIndex ");
		for (int i = 0; i < wf.size(); i++) {
			out.print(" " + (String) wf.elementAt(i));
		}
		out.println();
	}

	private void generateMimeMapping(PrintWriter out) {
		Node webN = wxml.getWebXmlNode();
		for (Node mapN = WebXml2Jk.getChild(webN, "mime-mapping"); mapN != null; mapN = WebXml2Jk
				.getNext(mapN)) {
			String ext = WebXml2Jk.getChildContent(mapN, "extension");
			String type = WebXml2Jk.getChildContent(mapN, "mime-type");

			out.println("  AddType " + type + " " + ext);
		}

	}

	public void generateEnd() {
		out.close();
	}

	public void generateServletMapping(String servlet, String url) {
		out.println("<Location \"" + cpath + url + "\" >");
		out.println("  SetHandler jakarta-servlet2");
		out.println("  JkUriSet group " + worker);
		out.println("  JkUriSet servlet " + servlet);
		out.println("  JkUriSet host " + vhost);
		out.println("  JkUriSet context " + cpath);
		out.println("</Location>");
		out.println();
	}

	public void generateFilterMapping(String servlet, String url) {
		out.println("<Location \"" + cpath + url + "\" >");
		out.println("  SetHandler jakarta-servlet2");
		out.println("  JkUriSet group " + worker);
		out.println("  JkUriSet servlet " + servlet);
		out.println("  JkUriSet host " + vhost);
		out.println("  JkUriSet context " + cpath);
		out.println("</Location>");
		out.println();
	}

	public void generateLoginConfig(String loginPage, String errPage,
			String authM) {
		out.println("<Location \"" + cpath + loginPage + "\" >");
		out.println("  SetHandler jakarta-servlet2");
		out.println("  JkUriSet group " + worker);
		out.println("  JkUriSet host " + vhost);
		out.println("  JkUriSet context " + cpath);
		out.println("</Location>");
		out.println();
	}

	public void generateErrorPage(int err, String location) {

	}

	// XXX Only if BASIC/DIGEST and 'integrated auth'
	public void generateConstraints(Vector urls, Vector methods, Vector roles,
			boolean isSSL) {
		for (int i = 0; i < urls.size(); i++) {
			String url = (String) urls.elementAt(i);

			out.println("<Location \"" + cpath + url + "\" >");

			if (methods.size() > 0) {
				out.print("  <Limit ");
				for (int j = 0; j < methods.size(); j++) {
					String m = (String) methods.elementAt(j);
					out.print(" " + m);
				}
				out.println(" >");
			}

			out.println("    AuthType basic");
			out.print("    Require group ");
			for (int j = 0; j < roles.size(); j++) {
				String role = (String) roles.elementAt(j);
				out.print(" " + role);
			}
			out.println();

			if (methods.size() > 0) {
				out.println("  </Limit>");
			}

			out.println("</Location>");
		}
	}
}
